using System;
using System.Collections.Specialized;
using System.Xml;
using System.Text;
using System.Text.RegularExpressions;
namespace AUSRIS.Reports.Utilities.Deployment
{
    /// <summary>
    /// Utility methods.
    /// </summary>
    public static class Util
    {
        /// <summary>
        /// Replaces the specified string to replace.
        /// </summary>
        /// <param name="stringToReplace">The string to replace.</param>
        /// <param name="oldValue">The old value.</param>
        /// <param name="newValue">The new value.</param>
        /// <returns></returns>
        public static string Replace(string stringToReplace, string oldValue, string newValue)
        {
            return Regex.Replace(stringToReplace, oldValue, newValue, RegexOptions.IgnoreCase | RegexOptions.Compiled);
        }

        /// <summary>
        /// Validates the distance.
        /// </summary>
        /// <param name="input">The input.</param>
        /// <returns></returns>
        public static bool ValidateDistance(string input)
        {
            Regex reg = new Regex(@"^\d+(\.\d*)*in$", RegexOptions.Compiled | RegexOptions.IgnoreCase);
            return reg.IsMatch(input);
        }

        /// <summary>
        /// Gets the XML namespace manager.
        /// </summary>
        /// <param name="input">The input.</param>
        /// <returns>The XML namespace manager</returns>
        public static XmlNamespaceManager GetXmlNamespaceManager(XmlDocument input)
        {
            StringCollection namespaces = DetectXmlNamespace(input);
            XmlNamespaceManager xnm = null;

            if(namespaces != null && namespaces.Count > 0)
            {
                xnm = new XmlNamespaceManager(input.NameTable);
                foreach(string ns in namespaces)
                {
                    string[] arr = ns.Split('|');
                    xnm.AddNamespace(arr[0].Trim(), arr[1].Trim());
                }
            }

            return xnm;
        }

        /// <summary>
        /// Detects the XML namespace.
        /// </summary>
        /// <param name="doc">The doc.</param>
        /// <returns></returns>
        private static StringCollection DetectXmlNamespace(XmlDocument doc)
        {
            StringCollection detectedNamespaces = null;

            if(doc != null)
            {
                XmlNode xmlNode = doc.DocumentElement;
                detectedNamespaces = new StringCollection();
                DiscoverNamespace(xmlNode, detectedNamespaces);
            }

            return detectedNamespaces;
        }

        /// <summary>
        /// Discovers the namespace.
        /// </summary>
        /// <param name="xmlNode">The XML node.</param>
        /// <param name="discovered">The discovered.</param>
        private static void DiscoverNamespace(XmlNode xmlNode, StringCollection discovered)
        {
            string nsPrefix;
            string nsUri;

            if(xmlNode.NodeType == XmlNodeType.Element)
            {
                if(xmlNode.Attributes.Count > 0)
                {
                    foreach(XmlAttribute attr in xmlNode.Attributes)
                    {
                        if(attr.Name.StartsWith("xmlns"))
                        {
                            string nsDef = attr.Name.Split('=')[0];
                            if(string.Compare(nsDef, "xmlns", true) != 0)
                            {
                                nsPrefix = nsDef.Split(':')[1];
                            }
                            else
                            {
                                nsPrefix = "def";
                            }
                            nsUri = attr.Value;

                            discovered.Add(string.Format("{0}|{1}", nsPrefix, nsUri));
                        }
                    }
                }
                if(xmlNode.HasChildNodes)
                {
                    foreach(XmlNode node in xmlNode.ChildNodes)
                    {
                        DiscoverNamespace(node, discovered);
                    }
                }
            }
        }

        /// <summary>
        /// Strings to byte array.
        /// </summary>
        /// <param name="input">The input.</param>
        /// <returns></returns>
        public static byte[] StringToByteArray(string input)
        {
            Byte[] data = new Byte[input.Length];
            char[] char1;

            char1 = input.ToCharArray();
            for(int i = 0; i < input.Length; i++)
            {
                data[i] = System.Convert.ToByte(char1[i]);
            }
            return data;
        }

        /// <summary>
        /// Formats the path.
        /// </summary>
        /// <param name="input">The input.</param>
        /// <returns></returns>
        public static string FormatPath(string input)
        {
            if(input == "/")
            {
                return input;
            }
            if(input != null && input.Trim().Length > 0)
            {
                string output = input.Replace("\\", "/");
                if(!output.StartsWith("/"))
                {
                    output = string.Format("/{0}", output);
                }
                if(output.EndsWith("/"))
                {
                    output = output.Substring(0, output.Length - 1);
                }
                return output;
            }
            else
            {
                return "/";
            }
        }

        /// <summary>
        /// Gets the relative path.
        /// </summary>
        /// <param name="source">The source.</param>
        /// <param name="target">The target.</param>
        /// <returns></returns>
        public static string GetRelativePath(string source, string target)
        {
            string pathSource = Util.FormatPath(source);
            string pathTarget = Util.FormatPath(target);
            string[] sourceSegments = null;
            string[] targetSegments = null;
            int sourceToCommonRoot = 0, targetToCommonRoot = 0;
            if(pathSource != "/")
            {
                sourceSegments = pathSource.Split('/');
                sourceToCommonRoot = sourceSegments.GetUpperBound(0);
            }
            if(pathTarget != "/")
            {
                targetSegments = pathTarget.Split('/');
                targetToCommonRoot = targetSegments.GetUpperBound(0);
            }
            StringBuilder relativePath = new StringBuilder();
            int parentSegments = sourceToCommonRoot;
            int i = 1;

            while(sourceToCommonRoot >= i && targetToCommonRoot >= i)
            {
                if(string.Compare(sourceSegments[i], targetSegments[i], true) == 0)
                {
                    parentSegments--;
                    i++;
                }
                else
                {
                    break;
                }
            }

            for(int k = 0; k < parentSegments; k++)
            {
                relativePath.Append("../");
            }

            for(int m = i; m <= targetToCommonRoot; m++)
            {
                relativePath.AppendFormat("{0}/", targetSegments[m]);
            }

            return relativePath.ToString();

        }
    }
}
